/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
 */

import { NormalizedFile } from '../../../../common/util/hvigor-file-util';
import { TrackAPI } from '../../../common/trace/hvigor-trace-factory.js';
import { hvigorCore } from '../../../external/core/hvigor-core.js';
import { HvigorCoreNode } from '../../../external/core/hvigor-core-node.js';
import { Consumer } from '../../../external/interface/consumer.js';
import { HvigorLogger } from '../../../log/hvigor-log.js';
import { TaskImpl } from '../../task/impl/task-impl.js';
import { HvigorTask } from '../../task/interface/hvigor-task.js';
import { Task } from '../../task/interface/task.js';
import { HvigorNode } from '../interface/hvigor-node.js';

/**
 * Hvigor Node节点实现类 (新)
 */
export class HvigorNodeImpl implements HvigorNode {
  private logger: HvigorLogger = HvigorLogger.getLogger(HvigorNodeImpl.name);
  private node: HvigorCoreNode;
  private allSubNodes: HvigorNode[] | [] = [];
  private parentNode: HvigorNode | undefined;
  nodeDir: NormalizedFile;

  /**
   * 可能存在工程名与模块名相同的情况，此时 this.getNodeName() 会返回相同的名字
   * 因此需要多加一个字段区分，可以是 'project' 或 'module'
   */
  classKind: string;

  constructor(node: HvigorCoreNode) {
    this.node = node;
    this.nodeDir = new NormalizedFile(node.getNodeDir());
    this.classKind = node.classKind;
    Object.freeze(this.nodeDir);
  }

  @TrackAPI getNodeName(): string {
    return this.node.getName();
  }

  @TrackAPI getNodePath(): string {
    return this.node.getNodeDir();
  }

  @TrackAPI getParentNode(): HvigorNode | undefined {
    this.loadParentNode();
    return this.parentNode;
  }

  @TrackAPI getContext(pluginId: string): any {
    return this.node.getContext(pluginId);
  }

  @TrackAPI getAllPluginIds(): string[] {
    return this.node.getAllPluginIds();
  }

  @TrackAPI getSubNodeByName(nodeName: string): HvigorNode | undefined {
    this.loadAllSubNodes();
    return this.allSubNodes.find((node) => node.getNodeName() === nodeName);
  }

  @TrackAPI getTaskByName(taskName: string): Task | undefined {
    const task = this.node.getTaskByName(taskName);
    if (!task) {
      this.logger.warn(`The task '${taskName}' cannot be found on the current node.`);
      return undefined;
    }
    return task.getHvigorTask();
  }

  @TrackAPI registerTask(task: HvigorTask): HvigorTask {
    return this.node.registerTask(task);
  }

  @TrackAPI subNodes(callbackfn: (node: HvigorNode) => void): void {
    this.loadAllSubNodes();
    this.allSubNodes.forEach((node: HvigorNode) => callbackfn(node));
  }
  @TrackAPI getNodeDir(): NormalizedFile {
    return this.nodeDir;
  }

  @TrackAPI getConfigOpt() {
    return this.node.getConfigOpt();
  }

  private loadParentNode(): void {
    this.parentNode = hvigorCore.getParentNodeByScriptPath(this.node.getBuildFilePath());
  }

  private loadAllSubNodes(): void {
    this.allSubNodes = hvigorCore.getSubNodeByScriptPath(this.node.getBuildFilePath()) ?? [];
  }

  @TrackAPI addExtraOption(key: string, value: any): void {
    this.node.addExtraOption(key, value);
  }

  @TrackAPI getExtraOption(key: string): any {
    return this.node.getExtraOption(key);
  }

  @TrackAPI beforeNodeEvaluate(fn: Consumer<HvigorNode>): void {
    this.node.beforeNodeEvaluate(fn);
  }

  @TrackAPI afterNodeEvaluate(fn: Consumer<HvigorNode>): void {
    this.node.afterNodeEvaluate(fn);
  }

  @TrackAPI getAllTasks(): Task[] {
    return this.node.getAllTasks().map((coreTask) => new TaskImpl(coreTask));
  }
}
